﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using CLEXA.DAL;
using CLEXA.DataContracts;
using CLEXA.Service.Helpers;
using CLEXA.ServiceContracts;

namespace CLEXA.Service
{
    public class ClientService : IClientService
    {
        private const string CONNECTION_STRING = @"Data Source=tcp:twwec9cw6n.database.windows.net,1433;Initial Catalog=clexa;Persist Security Info=True;User ID=clexa_user;Password = PASw0ord!;Pooling=False;";
        private readonly IDatabaseDAL databaseDAL;
        private readonly IUserDAL userDAL;
        private readonly ISchemaDAL schemaDAL;
        private readonly IPasswordHelper passwordHelper;
        private readonly IQueryBuilder queryBuilder;
        private readonly IHistogramDAL histogramDAL;

        public ClientService()
            : this(
            databaseDAL: new DatabaseDAL(CONNECTION_STRING),
            userDAL: new UserDAL(CONNECTION_STRING),
            schemaDAL: new SchemaDAL(),
            passwordHelper: new PasswordHelper(),
            queryBuilder: new QueryBuilder(),
            histogramDAL: new HistogramDAL())
        {

        }

        public ClientService(IDatabaseDAL databaseDAL, IUserDAL userDAL, ISchemaDAL schemaDAL, IPasswordHelper passwordHelper, IQueryBuilder queryBuilder, IHistogramDAL histogramDAL)
        {
            this.databaseDAL = databaseDAL;
            this.userDAL = userDAL;
            this.schemaDAL = schemaDAL;
            this.passwordHelper = passwordHelper;
            this.queryBuilder = queryBuilder;
            this.histogramDAL = histogramDAL;
        }

        public int CreateDatabase(int userId, string connectionString)
        {
            return databaseDAL.Insert(userId, connectionString);
        }

        public void DeleteDatabase(int databaseId)
        {
            databaseDAL.Delete(databaseId);
        }

        public void UpdateDatabase(DatabaseData database)
        {
            databaseDAL.Update(database);
        }

        public DatabaseData GetDatabase(int databaseId)
        {
            return databaseDAL.SelectByDatabaseId(databaseId);
        }

        public List<DatabaseData> GetDatabasesByUserId(int userId)
        {
            return databaseDAL.SelectByUserId(userId);
        }

        public List<TableData> GetSchema(string connectionString)
        {
            return schemaDAL.GetSchema(connectionString);
        }

        public int Login(string username, string password)
        {
            UserFullData user = userDAL.SelectByUsername(username);
            if (user == null)
            {
                //invalid username
                return 0;
            }
            if (!passwordHelper.IsPassword(user.HashedPassword, user.PasswordSalt, password))
            {
                //invalid password
                return 0;
            }
            if (!user.IsActive)
            {
                //user is disabled.
                return 0;
            }
            return user.UserId;
        }

        public bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            UserFullData user = userDAL.SelectByUsername(username);
            if (user == null)
            {
                //invalid username
                return false;
            }
            if (!passwordHelper.IsPassword(user.HashedPassword, user.PasswordSalt, oldPassword))
            {
                //invalid password
                return false;
            }
            if (!user.IsActive)
            {
                //user is disabled.
                return false;
            }
            string salt = passwordHelper.GenerateSalt();
            string hash = passwordHelper.Hash(newPassword, salt);
            userDAL.Update(new UserFullData(user.UserId, user.Username, user.IsActive, hash, salt));
            return true;
        }

        public List<HistogramRowData> ComputeHistograms(string connectionString, QueryData queryData)
        {
            string sql = queryBuilder.GenerateSQL(queryData);
            return histogramDAL.ExecuteQuery(connectionString, sql);
        }
    }
}
